/*
13、不同的子序列
2022-11-2
link: https://leetcode.cn/problems/distinct-subsequences/
question:
	给定一个字符串 s 和一个字符串 t ，计算在 s 的子序列中 t 出现的个数。
	字符串的一个 子序列 是指，通过删除一些（也可以不删除）字符且不干扰剩余字符相对位置所组成的新字符串。
	（例如，"ACE" 是 "ABCDE" 的一个子序列，而 "AEC" 不是）
	题目数据保证答案符合 32 位带符号整数范围。
answer:
	这道题目如果不是子序列，而是要求连续序列的，那就可以考虑用KMP。
	动态规划五步曲：
	1、dp数组和下标含义：
		dp[i][j]：以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。
	2、递推公式
		当s[i - 1] 与 t[j - 1]相等时，dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
		当s[i - 1] 与 t[j - 1]不相等时，dp[i][j]只有一部分组成，不用s[i - 1]来匹配，即：dp[i - 1][j]
		所以递推公式为：dp[i][j] = dp[i - 1][j];
	3、初始化
		dp[i][0] 表示：以i-1为结尾的s可以随便删除元素，出现空字符串的个数。
		那么dp[i][0]一定都是1，因为也就是把以i-1为结尾的s，删除所有元素，出现空字符串的个数就是1。
		再来看dp[0][j]，dp[0][j]：空字符串s可以随便删除元素，出现以j-1为结尾的字符串t的个数。
		那么dp[0][j]一定都是0，s如论如何也变成不了t。
		dp[0][0]应该是1，空字符串s，可以删除0个元素，变成空字符串t。
	4、遍历顺序
		从上到下，从左到右，这样保证dp[i][j]可以根据之前计算出来的数值进行计算。
	5、举例推导
*/
func numDistinct(s string, t string) int {
	// dp数组和初始化
	dp := make([][]int, len(s)+1)
	for i := 0; i <= len(s); i++ {
		dp[i] = make([]int, len(t)+1)
		dp[i][0] = 1 // 第一列初始化为1，其他为0或默认值
	}
	for i := 1; i <= len(s); i++ {
		for j := 1; j <= len(t); j++ {
			if s[i-1] == t[j-1] {
				dp[i][j] = dp[i-1][j-1] + dp[i-1][j] // 注意，这里不一样
			} else {
				dp[i][j] = dp[i-1][j] // 注意这里递推公式
			}
		}
	}
	return dp[len(s)][len(t)]

}